﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IDLETD.Math
{
    /// <summary>
    /// 3D向量类
    /// </summary>
    public class Vector3D
    {
        public float X { get; set; }
        public float Y { get; set; }
        public float Z { get; set; }

        public Vector3D()
        {

        }

        public Vector3D(Vector3D v)
        {
            X = v.X;
            Y = v.Y;
            Z = v.Z;
        }

        public Vector3D(float x, float y, float z)
        {
            X = x;
            Y = y;
            Z = z;
        }

        #region 运算符
        public static bool operator ==(Vector3D v1, Vector3D v2)
        {
            return v1.X == v2.X && v1.Y == v2.Y && v1.Z == v2.Z;
        }

        public static bool operator !=(Vector3D v1, Vector3D v2)
        {
            return v1.X != v2.X || v1.Y != v2.Y || v1.Z != v2.Z;
        }

        public static Vector3D operator -(Vector3D v)
        {
            return new Vector3D(-v.X, -v.Y, -v.Z);
        }

        public static Vector3D operator +(Vector3D v1, Vector3D v2)
        {
            return new Vector3D(v1.X + v2.X, v1.Y + v2.Y, v1.Z + v2.Z);
        }

        public static Vector3 operator -(Vector3 v1, Vector3 v2)
        {
            return new Vector3(v1.X - v2.X, v1.Y - v2.Y, v1.Z - v2.Z);
        }

        /// <summary>
        /// 与标量相乘
        /// </summary>
        /// <param name="v"></param>
        /// <param name="a"></param>
        /// <returns></returns>
        public static Vector3 operator *(Vector3 v, float a)
        {
            return new Vector3(v.X * a, v.Y * a, v.Z * a);
        }

        /// <summary>
        /// 与标量相除
        /// </summary>
        /// <param name="v"></param>
        /// <param name="a"></param>
        /// <returns></returns>
        public static Vector3 operator /(Vector3 v, float a)
        {
            float oneOverA = 1.0f / a;//:这里不对除零进行检查
            return new Vector3(v.X * oneOverA, v.Y * oneOverA, v.Z * oneOverA);
        }

        // +=运算符不可显式重载，会随着+运算符的重载而隐式重载
        // -=运算符不可显式重载，会随着-运算符的重载而隐式重载
        // *=运算符不可显式重载，会随着*运算符的重载而隐式重载
        // /=运算符不可显式重载，会随着/运算符的重载而隐式重载

        /// <summary>
        /// 向量点乘，重载标准乘法运算符.
        /// </summary>
        /// <param name="v1"></param>
        /// <param name="v2"></param>
        /// <returns></returns>
        public static float operator *(Vector3 v1, Vector3 v2)
        {
            return v1.X * v2.X + v1.Y * v2.Y + v1.Z * v2.Z;
        }

        public override bool Equals(object v)
        {
            if (!(v is Vector3))
            {
                return false;
            }
            return this == (v as Vector3);
        }

        /// <summary>
        /// 向量左乘
        /// </summary>
        /// <param name="a"></param>
        /// <param name="v"></param>
        /// <returns></returns>
        public static Vector3 operator *(float a, Vector3 v)
        {
            return new Vector3(a * v.X, a * v.Y, a * v.Z);
        }
        #endregion


        /// <summary>
        /// 置为零微量
        /// </summary>
        public void Zero()
        {
            X = Y = Z = 0.0f;
        }


        /// <summary>
        /// 向量标准化
        /// </summary>
        public void Normalize()
        {
            float magSq = X * X + Y * Y + Z * Z;
            if (magSq > 0.0f)//检查除零
            {
                float oneOverMag = (float)(1.0f / Math.Sqrt(magSq));
                X *= oneOverMag;
                Y *= oneOverMag;
                Z *= oneOverMag;
            }
        }

        /// <summary>
        /// 求向量模
        /// </summary>
        /// <returns></returns>
        public float VectorMag()
        {
            return (float)(Math.Sqrt(X * X + Y * Y + Z * Z));
        }

        /// <summary>
        /// 计算两向量的叉乘
        /// </summary>
        /// <returns></returns>
        public Vector3D CorssProduct(Vector3D v)
        {
            return new Vector3D(Y * v.Z - Z * v.Y,
                               Z * v.X - X * v.Z,
                               X * v.Y - Y * v.X);
        }

        /// <summary>
        /// 计算两点间的距离
        /// </summary>
        /// <param name="v"></param>
        /// <returns></returns>
        public float Distance(Vector3D v)
        {
            float dx = X - v.X;
            float dy = Y - v.Y;
            float dz = Z - v.Z;
            return (float)Math.Sqrt(dx * dx + dy * dy + dz * dz);
        }

        public override String ToString()
        {
            return String.Format("X:{0},Y:{1},Z:{2}", X, Y, Z);
        }
        #endregion
    }
}
